# coding:utf-8
# writingtime: 2022-6-28
# author: wanjun
import os
import datetime

from Utilities.ConstructData.DistributionFunctionData import Distribute
from Utilities.AutoGetOperator.selectionMethod.selectPackage import get_func
from Utilities.Plot.SimplePlot import SimpleClass
from Utilities.Plot.Plot3D import Plot3D


class Op_Analyze():
    def __init__(self,operator,getExpertWeight,getAttributeWeight,scoreFunction,
                 get_data,q=3,x=2,a=2,b=4,*wast1,**waste2):
        '''
        function: 测试单个算子
        :param operator: 算子函数
        :param getExpertWeight: 专家权重计算函数
        :param getAttributeWeight: 属性权重计算函数
        :param data_group: 决策数据群
        :param q: q
        :param x: 算子1个参数用x
        :param a: 算子需要两个参数用a，b
        :param b: 算子需要两个参数用a，b
        '''

        self.operator=operator                                  # 算子函数
        self.getAttributeWeight=getAttributeWeight              # 计算属性权重方式
        self.getScore=scoreFunction                             # 得分函数
        self.get_dataGroup=get_data
        self.getExpertWeight=getExpertWeight                    # 计算专家权重的方式
        self.data_group=[]                                      # 决策群
        self.expert_weight=[]                                   # 专家权重
        self.attribute_weight=[]                                # 属性权重
        self.q=q
        self.x=x
        self.a=a
        self.b=b


    def set_dataGroup(self,data_group):
        '''
        function: 设置决策数据群
        :param data_group: 决策群
        :return:
        '''
        self.data_group=data_group

    def setExpertWeight(self,expert_weight):
        '''
        function: 设置专家权重
        :param weight_weight:专家权重
        :return:
        '''
        self.expert_weight=expert_weight

    def setAttributeWeight(self,attribute_weight):
        '''
        function: 设置属性权重
        :param attribute_weight: 属性权重
        :return:
        '''
        self.attribute_weight=attribute_weight

    def set_q(self,q):
        '''
        function: 对q的值进行修改
        :param q:
        :return:
        '''
        self.q=q

    def set_x(self,x):
        '''
        function: 对x的值进行修改
        :param x:
        :return:
        '''
        self.x=x

    def set_a(self,a):
        '''
        function: 对a的值进行修改
        :param a:
        :return:
        '''
        self.a=a

    def set_b(self,b):
        '''
        function: 对b的值进行修改
        :param b:
        :return:
        '''
        self.b=b

    def matrixReverse(self,matrix):
        '''
        function: 功能函数
        :param matrix: 矩阵
        :return: 行列交换的矩阵
        '''
        newMatrix = []
        for x in range(len(matrix[0])):
            temp = []
            for y in range(len(matrix)):
                temp.append(matrix[y][x])
            newMatrix.append(temp)

        return newMatrix

    def arrge(self):
        '''
        function: 对决策群进行集结
        :return:
        '''

        aggre_matrix_1 = []  # 存放运算结果
        '''集结矩阵'''
        for i in range(len(self.data_group[0])):
            li_1 = []
            for j in range(len(self.data_group[0][0])):
                li_1.append(
                    self.operator([self.data_group[k][i][j] for k in range(len(self.data_group))], self.expert_weight,
                             self.q,self.x).getResult())
            aggre_matrix_1.append(li_1)
        # 属性权重,对于属性进行分析，因此需要翻转
        # reverseMatrix=self.matrixReverse(aggre_matrix_1)
        # self.attr_weight = self.getAttributeWeight(aggre_matrix_1,
        #                     [1 / len(aggre_matrix_1[0]) for i in range(len(aggre_matrix_1[0]))],
        #                     self.q).getResult()
        self.attr_weight = self.getAttributeWeight(aggre_matrix_1,self.b, self.q).getResult()
        # 最终结果
        fianl_vlaue = [self.operator(i, self.attr_weight, self.q).getResult() for i in aggre_matrix_1]
        return fianl_vlaue

    def saveData(self,fname='1.txt',data_group=[],expertWeight=[],atttributeWeight=[],q_range=[]):
        '''
        function: 存储数据
        :param data_group: 决策群
        :param expertWeight: 专家权重
        :param atttributeWeight: 属性权重
        :param q:
        :return:
        '''

        # 写入data数据
        try:
            data_file = open(fname, "w")
            data_file.write("q:\n" + str(q_range) + "\n" +
                            "data set:\n" + str(data_group) + "\n" +
                            "expert weight:\n" + str(expertWeight) + "\n"
                            "attribute weight:\n" + str(atttributeWeight) + "\n")
            print(fname + " is saved")
            data_file.close()
        except:
            print(fname + " fail")
        # 存储数据

    def q_analyze(self,q_min,q_max):
        '''
        function: q的敏感度分析
        :param q_min: q的下限，不能小于决策数据中最的最小q值
        :param q_max: q的上限
        :return:
        '''
        # 创建文件夹
        root_path = os.path.realpath(os.path.dirname(os.path.dirname(__file__)))
        path = os.path.join(root_path, r'Data\randonData\OneOperatorAnalyze\get_Gaussian_random')
        path = os.path.join(path, datetime.datetime.now().strftime('%Y-%m-%d'))
        fpath = os.path.join(path, r'img')
        tpath = os.path.join(path, r'data')
        try:
            os.makedirs(fpath) # 图片存储地址
            os.makedirs(tpath) # 数据存储地址
        except:
            print('folder already exists')



        for plan_n in range(5,6):
            for expe_n in range(3,4):
                for attr_n in range(5,6):
                    # 随机生成决策群
                    # data=self.get_dataGroup(plan_n,expe_n,attr_n).get_Uniform_random(get_return=True)
                    data = [[[([0.05506, 0.15007], [0.84993, 0.94494]), ([0.81013, 0.90506], [0.09494, 0.18987]),
                              ([0.47918, 0.57918], [0.42082, 0.52082]), ([0.08603, 0.18447], [0.81553, 0.91397]),
                              ([0.91838, 0.9647], [0.0353, 0.08162])],
                             [([0.15596, 0.28394], [0.71606, 0.84404]), ([0.92559, 0.97047], [0.02953, 0.07441]),
                              ([0.11522, 0.22283], [0.77717, 0.88478]), ([0.24461, 0.37974], [0.62026, 0.75539]),
                              ([0.54156, 0.64156], [0.35844, 0.45844])],
                             [([0.28054, 0.40369], [0.59631, 0.71946]), ([0.74251, 0.86168], [0.13832, 0.25749]),
                              ([0.03474, 0.12749], [0.87251, 0.96526]), ([0.24081, 0.37721], [0.62279, 0.75919]),
                              ([0.55611, 0.65917], [0.34083, 0.44389])],
                             [([0.503, 0.603], [0.397, 0.497]), ([0.59365, 0.71548], [0.28452, 0.40635]),
                              ([0.45631, 0.55631], [0.44369, 0.54369]), ([0.08175, 0.17973], [0.82027, 0.91825]),
                              ([0.2189, 0.3626], [0.6374, 0.7811])],
                             [([0.04656, 0.14062], [0.85938, 0.95344]), ([0.19148, 0.33722], [0.66278, 0.80852]),
                              ([0.85943, 0.92972], [0.07028, 0.14057]), ([0.63435, 0.77652], [0.22348, 0.36565]),
                              ([0.90992, 0.95794], [0.04206, 0.09008])]], [
                                [([0.29453, 0.41302], [0.58698, 0.70547]), ([0.08932, 0.18813], [0.81187, 0.91068]),
                                 ([0.52587, 0.62587], [0.37413, 0.47413]), ([0.52938, 0.62938], [0.37062, 0.47062]),
                                 ([0.16028, 0.29042], [0.70958, 0.83972])],
                                [([0.21864, 0.36243], [0.63757, 0.78136]), ([0.87408, 0.93704], [0.06296, 0.12592]),
                                 ([0.67175, 0.8145], [0.1855, 0.32825]), ([0.02805, 0.12006], [0.87994, 0.97195]),
                                 ([0.12622, 0.23932], [0.76068, 0.87378])],
                                [([0.47499, 0.57499], [0.42501, 0.52501]), ([0.35713, 0.45713], [0.54287, 0.64287]),
                                 ([0.32095, 0.43063], [0.56937, 0.67905]), ([0.28179, 0.40453], [0.59547, 0.71821]),
                                 ([0.10593, 0.2089], [0.7911, 0.89407])],
                                [([0.02361, 0.11512], [0.88488, 0.97639]), ([0.67097, 0.81398], [0.18602, 0.32903]),
                                 ([0.61201, 0.74302], [0.25698, 0.38799]), ([0.16409, 0.29614], [0.70386, 0.83591]),
                                 ([0.3502, 0.4502], [0.5498, 0.6498])],
                                [([0.27301, 0.39868], [0.60132, 0.72699]), ([0.83719, 0.9186], [0.0814, 0.16281]),
                                 ([0.16518, 0.29777], [0.70223, 0.83482]), ([0.18927, 0.3339], [0.6661, 0.81073]),
                                 ([0.47597, 0.57597], [0.42403, 0.52403])]], [
                                [([0.90745, 0.95596], [0.04404, 0.09255]), ([0.93388, 0.97711], [0.02289, 0.06612]),
                                 ([0.10101, 0.20151], [0.79849, 0.89899]), ([0.74357, 0.86238], [0.13762, 0.25643]),
                                 ([0.8615, 0.93075], [0.06925, 0.1385])],
                                [([0.12155, 0.23232], [0.76768, 0.87845]), ([0.52818, 0.62818], [0.37182, 0.47182]),
                                 ([0.14562, 0.26843], [0.73157, 0.85438]), ([0.03427, 0.12696], [0.87304, 0.96573]),
                                 ([0.83094, 0.91547], [0.08453, 0.16906])],
                                [([0.01584, 0.10649], [0.89351, 0.98416]), ([0.60119, 0.72679], [0.27321, 0.39881]),
                                 ([0.35661, 0.45661], [0.54339, 0.64339]), ([0.95, 0.99], [0.01, 0.05]),
                                 ([0.12524, 0.23786], [0.76214, 0.87476])],
                                [([0.92401, 0.96921], [0.03079, 0.07599]), ([0.35232, 0.45232], [0.54768, 0.64768]),
                                 ([0.58851, 0.70777], [0.29223, 0.41149]), ([0.46995, 0.56995], [0.43005, 0.53005]),
                                 ([0.66345, 0.80897], [0.19103, 0.33655])],
                                [([0.82414, 0.91207], [0.08793, 0.17586]), ([0.93183, 0.97546], [0.02454, 0.06817]),
                                 ([0.67167, 0.81445], [0.18555, 0.32833]), ([0.05878, 0.1542], [0.8458, 0.94122]),
                                 ([0.42866, 0.52866], [0.47134, 0.57134])]]]

                    # 更新决策群
                    self.set_dataGroup(data)
                    # 更新专家权重
                    self.expert_weight = self.getExpertWeight(self.data_group)
                    value_list=[]
                    for i in range(q_min,q_max+1):
                        self.set_q(i)
                        temp=self.arrge()
                        value_list.append([self.getScore(temp[i],self.q).getScore() for i in range(plan_n)])
                        # print([self.getScore(temp[i],self.q).getScore() for i in range(plan_n)])
                    # 将结果转置
                    # print(self.expert_weight)
                    self.attr_weight = [0.14031104, 0.16207846, 0.21293963, 0.22940427, 0.2552666 ]
                    value_list=self.matrixReverse(value_list)
                    # 保存结果
                    fname=os.path.join(fpath,str(plan_n)+'_'+str(expe_n)+'_'+str(attr_n)+'.png')

                    tname=os.path.join(tpath,str(plan_n)+'_'+str(expe_n)+'_'+str(attr_n)+'.txt')
                    self.saveData(tname,self.data_group,self.expert_weight,self.attr_weight,[q_min+i for i in range(q_max-q_min+1)])
                    # print(fname,'is saved')
                    SimpleClass().qSensitivity(value_list,[q_min+i for i in range(q_max-q_min+1)],title=self.operator.__name__,
                                               filename=fname,imgSaving=True,imgShow=False)
                    # Plot3D().heatMap(value_list,[q_min+i for i in range(q_max-q_min+1)],title=self.operator.__name__,
                    #                            filename=fname,imgSaving=True,imgShow=False)


if __name__=='__main__':
    root_path = os.path.realpath(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
    attributeMethod=get_func(root_path+r'\IVq-ROFSSBM\DecisionMethod\SEAC.py','SEAC')
    expertMethod=get_func(root_path+r"\IVq-ROFSSBM\Utilities\GetWeight\getExpertWeight\GetSatisfactionWeight.py",'getSatisfactionWeight')

    scoreFunction=get_func(root_path+r'\IVq-ROFSSBM\ScoreFunction\getS.py','getS')
    data_class=get_func(root_path+r'\IVq-ROFSSBM\Utilities\ConstructData\DistributionFunctionData.py','Distribute')
    operator = get_func(root_path + r'\IVq-ROFSSBM\Operators\BonferroniMean.py','SchweizerSklarBonferroniMeanWA')
    # operator = get_func(root_path + r'\DecisionSystem\Operators\FunctionOperators\AssociatedProbabilities.py','AssociatedProbabilitiesWA')
    # operator = get_func(root_path + r'\DecisionSystem\Operators\OperationOperators\Einstein.py','EinsteinWA')
    # Operators / FunctionOperators / BonferroniMean.py
    # Operators / OperationOperators / Einstein.py
    test=Op_Analyze(operator,expertMethod,attributeMethod,scoreFunction,data_class)
    # test.set_x(-4)
    test.q_analyze(2,7)
    # test.saveData()






